;-*-Lisp-*-

;;;
;;; rglib 0.1
;;; library for rgblog 
;;;


;;
;; global vars
;;


(defparameter *query-string* (ext:getenv "QUERY_STRING"))




;;
;; utility
;;


(defun parse-query-string (query-string)
  (if (string> query-string "q=")(string-downcase (subseq query-string 2))))

(defun file->string (path)
  (with-open-file (s path)
    (let* 
	((len (file-length s))
	 (data (make-string len)))
      (values data (read-sequence data s)))))

(defun lines-in-file (file)
  (let ((count 0))
    (with-open-file (stream file)
      (do ((post (read stream nil)
		 (read stream nil)))
	  ((null post))
	(incf count)))
    count))

(defun get-pretty-date (universal-time)
  (multiple-value-bind 
	(second minute hour date month year day-of-week dst-p tz)
      (decode-universal-time universal-time)
    (format nil "~@(~a~) ~a, ~a" (nth month *month-names*) date year)))



;;
;; authoring
;;


(defun make-post (postid name body)
  (list :postid postid :name name :body body))

(defun prompt-read (prompt)
  (format *query-io* "~a: " prompt)
  (force-output *query-io*)
  (read-line *query-io*))

(defun prompt-for-post()
  (make-post
   (write-to-string (get-universal-time))
   (prompt-read "Title ")
   (prompt-read "Entry ")))

(defmacro add-post (file)
  `(save-post (prompt-for-post) ,file))

(defun add ()
  (add-post *posts-file*))



;;
;; output
;;


(defmacro apply-template (template &rest strings)
  `(format nil (file->string ,template) ,@strings))

(defun print-post (post template)
  (apply-template template 
   (getf post :name)
   (getf post :body) 
   (get-pretty-date (parse-integer (getf post :postid)))
   (getf post :postid)))

(defun print-posts (limit file template)
  (let ((res "")
	(start (- (lines-in-file file) limit))
	(idx 0))
    (with-open-file (stream file)
      (do ((post (read stream nil)
		 (read stream nil)))
	  ((null post))
	(progn
	  (incf idx)
	  (if (> idx start) 
	      (setf res 
		    (concatenate 'string (print-post post template) res))))))
    res))

(defun print-main (title body template)
    (apply-template template title title body))

(defun print-archive ()
  (format t "~a" 
	  (print-main 
	   *archives-title*
	   (print-posts 1000 *posts-file* *archive-post-template*) 
	   *archive-template*)))

(defun print-permalink-post ()
  (let ((post 
	 (open-post (parse-query-string *query-string*) *posts-file*)))
    (format t "~a" 
	    (print-main 
	     (getf post :name) 
	     (print-post post *post-template*) 
	     *index-template*))))

(defun print-index ()
  (format t "~a" 
	  (print-main 
	   *blog-title* 
	   (print-posts *post-limit* *posts-file* *post-template*) 
	   *index-template*)))



;;
;; data
;;


(defun save-post (post filename)
  (with-open-file (out filename
		       :direction :output
       		       :if-exists :append
		       :if-does-not-exist :create)
    (with-standard-io-syntax
      (print post out))))

(defun open-post (postid file)
  (let ((res nil))
    (with-open-file (stream file)
      (do ((post (read stream nil)
		 (read stream nil)))
	  ((null post))
	(if (equal postid (getf post :postid)) 
	    (setf res post))))
    res))



;;
;; main routines
;;

(defun exec ()
    (funcall (read-from-string (first ext:*args*))))

(defun main ()
    (cond
      ((equal (parse-query-string *query-string*) "archives")
       (print-archive))
      ((open-post (or (parse-query-string *query-string*) "0") *posts-file*)
       (print-permalink-post))
      (t
       (print-index))))
			

